<template>
  <div class="contain">
    <h1>保存的连接</h1>
    <el-row>
      <el-button type="primary" plain @click="beforeOpenGroupDialog(null)">添加分组</el-button>
      <el-button type="primary" plain @click="importConnectionDialog = true">导入连接</el-button>
      <el-button type="primary" plain @click="exportConnectionDialog = true">导出连接</el-button>
    </el-row>
    <el-row style="margin-top: 20px;">
      <el-collapse>
        <el-empty v-if="groups.length < 1" :image-size="150" description="暂无数据"></el-empty>
        <el-collapse-item v-for="(group, index) in groups" :key="index">
          <h4 slot="title">
            {{ group.name }}
          </h4>
          <el-row>
            <el-popconfirm title="确定要删除连接吗？" confirm-button-text="确认"
                           confirm-button-type="danger" cancel-button-text="取消" @confirm="removeConnects">
              <el-button slot="reference" type="danger" plain>删除连接</el-button>
            </el-popconfirm>
            <el-divider direction="vertical"></el-divider>
            <el-popconfirm title="确定要删除分组吗？" confirm-button-text="确认"
                           confirm-button-type="danger" cancel-button-text="取消"
                           @confirm="deleteGroupAndData(group)">
              <el-button slot="reference" type="danger" plain>删除分组</el-button>
            </el-popconfirm>
            <el-divider direction="vertical"></el-divider>
            <el-button type="warning" plain @click="beforeOpenGroupDialog(group)">编辑分组</el-button>
          </el-row>
          <!-- 连接数据 -->
          <el-table
              ref="multipleTable"
              :data="group.connectionList"
              tooltip-effect="dark"
              @selection-change="handleSelectionChange">
            <el-table-column type="selection" width="55">
            </el-table-column>
            <el-table-column label="连接名" width="120px">
              <template slot-scope="scope">{{ scope.row.name }}</template>
            </el-table-column>
            <el-table-column prop="uri" label="URI">
            </el-table-column>
            <el-table-column prop="updateTime" label="时间">
            </el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button @click="openConnection(scope.row)" type="text" size="small">打开连接</el-button>
                <el-button @click="beforeOpenConnectDialog(scope.row)" type="text" size="small">编辑连接</el-button>
                <el-button @click="copyConnectionString(scope.row)" type="text" size="small">复制连接字符串
                </el-button>
                <el-button @click="duplicate(scope.row)" type="text" size="small">复制连接</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-collapse-item>
      </el-collapse>
    </el-row>

    <!-- 添加和编辑分组对话框 -->
    <el-dialog :title="dialogTitle" :visible.sync="groupDialog" :close-on-click-modal="false"
               @opened="openGroupDialog" @closed="closeGroupDialog" width="30%">
      <el-form :model="addGroup" label-position="top" size="small">
        <el-form-item label="分组名" label-width="50px">
          <el-input v-model="addGroup.name" :autofocus="true" ref="groupInput" placeholder="Group Name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="groupDialog = false">取消</el-button>
        <el-button type="primary" @click="saveGroup" :disabled="groupIsDisabled">保存</el-button>
      </span>
    </el-dialog>

    <!-- 编辑连接对话框 -->
    <el-dialog :title="dialogTitle" :visible.sync="connectDialog" :close-on-click-modal="false"
               @opened="openConnectDialog" @closed="closeConnectDialog" width="30%">
      <el-form :model="connectForm" label-position="right" size="small" inline>
        <el-form-item label="连接名">
          <el-input v-model="connectForm.name" :autofocus="true" ref="nameInput" placeholder="Connect Name"></el-input>
        </el-form-item>
        <el-form-item label="分组名">
          <el-select v-model="connectForm.groups" placeholder="请选择" clearable filterable default-first-option>
            <el-option v-for="item in saveConnectionGroups" :key="item.id" :label="item.groupName" :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="协议">
          <el-radio-group v-model="connectForm.protocol">
            <el-radio-button label="mongodb"></el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="IP地址">
          <el-input v-model="connectForm.ip" :placeholder="connectForm.ip"></el-input>
        </el-form-item>
        <el-form-item label="端口">
          <el-input v-model="connectForm.port" :placeholder="connectForm.port"></el-input>
        </el-form-item>
        <el-form-item label="认证方式">
          <el-switch
              v-model="connectForm.auth"
              active-text="用户名密码认证"
              inactive-text="无">
          </el-switch>
        </el-form-item>
        <template v-if="connectForm.auth">
          <el-form-item label="用户名">
            <el-input v-model="connectForm.username" placeholder="UserName"></el-input>
          </el-form-item>
          <el-form-item label="密码">
            <el-input v-model="connectForm.password" type="password" placeholder="PassWord"></el-input>
          </el-form-item>
          <el-form-item label="权限数据库">
            <el-input v-model="connectForm.authDatabase" placeholder="可选的，默认 admin"></el-input>
          </el-form-item>
          <el-form-item label="认证机制">
            <el-radio-group v-model="connectForm.authMechanism">
              <el-radio-button label="DEFAULT"></el-radio-button>
              <el-radio-button label="SCRAM-SHA-1"></el-radio-button>
              <el-radio-button label="SCRAM-SHA-256"></el-radio-button>
            </el-radio-group>
          </el-form-item>
        </template>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="connectDialog = false">取消</el-button>
        <el-button type="primary" @click="saveConnect" :disabled="connectIsDisabled">保存</el-button>
      </span>
    </el-dialog>

    <!-- 导入连接对话框 -->
    <el-dialog title="导入连接" :visible.sync="importConnectionDialog" :close-on-click-modal="false"
               @opened="openImportConnectionDialog" @closed="closeImportConnectionDialog" width="30%">
      <el-form label-position="top" size="small">
        <el-upload action="none" :accept="'.json'" :auto-upload="false"
                   :limit="1" :on-change="importFileChange" :on-exceed="importExceed">
          <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
          <div class="el-upload__tip" slot="tip">只能上传 json 文件，且不超过 10MB</div>
        </el-upload>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="importConnectionDialog = false">取消</el-button>
        <el-button type="primary" :disabled="importConnectionIsDisabled" @click="ImportConnection">导入</el-button>
      </span>
    </el-dialog>

    <!-- 导出连接对话框 -->
    <el-dialog title="导出连接" :visible.sync="exportConnectionDialog" :close-on-click-modal="false"
               @opened="openExportConnectionDialog" @closed="closeExportConnectionDialog" width="60%">
      <el-empty v-if="exportList.length < 1" :image-size="150" description="未选择数据"></el-empty>
      <el-table v-else :data="exportList" style="width: 100%">
        <el-table-column prop="groupName" label="分组名" width="180"/>
        <el-table-column prop="name" label="连接名" width="180"/>
        <el-table-column prop="uri" label="URI"/>
        <el-table-column prop="updateTime" label="时间"/>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="exportConnectionDialog = false">取消</el-button>
        <el-button type="primary" :disabled="exportConnectionIsDisabled" @click="ExportConnection">导出</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import {addGroup, removeGroup, getAllGroup, editGroup} from "@/api/group";
import {
  addConnection,
  editConnection,
  getAllSaveConnectList,
  importSaveConnectList,
  removeSaveConnects
} from "@/api/saveConnect";
import FileSaver from 'file-saver'

export default {
  name: "Save",
  data() {
    return {
      groups: [],
      connectionMultipleSelection: [],
      dialogTitle: '',
      groupDialog: false,
      importConnectionDialog: false,
      exportConnectionDialog: false,
      addGroup: {
        name: null
      },
      groupIsDisabled: true,
      connectDialog: false,
      connectIsDisabled: true,
      connectForm: {
        id: null,
        name: null,
        groups: null,
        protocol: null,
        ip: null,
        port: null,
        auth: null,
        username: null,
        password: null,
        authDatabase: null,
        authMechanism: null,
      },
      saveConnectionGroups: [],
      importConnectionIsDisabled: true,
      importDate: null,
      exportList: [],
      exportConnectionIsDisabled: true
    }
  },
  watch: {
    addGroup: {
      handler() {
        this.groupIsDisabled = !(this.addGroup.name != null && this.addGroup.name.length !== 0);
      },
      deep: true
    },
    connectForm: {
      handler(newVal) {
        if (newVal.auth) {
          this.connectIsDisabled = ((newVal.username === null || newVal.username === '')
              || (newVal.password === null || newVal.password === '')
              || (newVal.authMechanism === null || newVal.authMechanism === ''))
        } else {
          this.connectIsDisabled = ((newVal.name === null || newVal.name === '')
              || (newVal.groupId === null || newVal.groupId === '')
              || (newVal.protocol === null || newVal.protocol === '')
              || (newVal.ip === null || newVal.ip === '')
              || (newVal.port === null || newVal.port === ''))
        }
      },
      deep: true
    },
    importFileList: {
      handler(newVal) {
        this.importConnectionIsDisabled = newVal == null || newVal.length < 1
      }
    },
    exportList: {
      handler() {
        this.exportConnectionIsDisabled = this.exportList.length <= 0;
      }
    }
  },
  mounted() {
    if (this.$store.getters.getToken === null) {
      this.$router.push('/newConnection')
    } else {
      this.getSaveConnectList()
      getAllGroup().then(res => {
        this.saveConnectionGroups = res.data
      })
    }
  },
  methods: {
    getSaveConnectList() {
      const loading = this.$loading({
        lock: true,
        text: '加载数据中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        getAllSaveConnectList().then(res => {
          let groups = []
          res.data.forEach(item => {
            let group = {}
            group.name = item.group.groupName
            group.id = item.group.id
            let connectList = []
            item.connectionList.forEach(connect => {
              if (connect.auth) {
                connect.uri = connect.protocol + '://' + connect.username + ':******@' + connect.ip + ':' + connect.port + '/?authMechanism=' + connect.authMechanism + '&authSource=' + connect.authDatabase
              } else {
                connect.uri = connect.protocol + "://" + connect.ip + ":" + connect.port + "/"
              }
              connectList.push(connect)
            })
            group.connectionList = connectList
            groups.push(group)
          })
          this.groups = groups
        }).catch(() => {
          this.$router.push('/newConnection')
        })
      }, 1000);
    },
    removeConnects() {
      let ids = []
      this.connectionMultipleSelection.forEach(connect => {
        ids.push(connect.id)
      })
      if (ids.length < 1) {
        this.$message({
          message: '请选择要删除的连接！',
          type: 'error'
        });
      } else {
        const loading = this.$loading({
          lock: true,
          text: '删除中...',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });
        setTimeout(() => {
          loading.close();
          removeSaveConnects(ids).then(() => {
            this.$message.success("成功删除连接！")
            this.getSaveConnectList();
          }).catch(() => {
            this.$message.error("删除连接失败！")
          })
        }, 1000);
      }
    },
    deleteGroupAndData(group) {
      const loading = this.$loading({
        lock: true,
        text: '删除中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        removeGroup(group.id).then(() => {
          this.$message.success("成功删除分组及其连接！")
          this.getSaveConnectList();
        }).catch(() => {
          this.$message.error("删除分组及其连接失败！")
        })
      }, 1000);
    },
    beforeOpenGroupDialog(group) {
      if (group === null || group === undefined) {
        // save
        this.dialogTitle = '添加分组'
      } else {
        // edit
        this.dialogTitle = '编辑分组'
        this.addGroup.id = group.id
        this.addGroup.name = group.name
      }
      this.groupDialog = true
    },
    openGroupDialog() {
      this.$refs.groupInput.focus();
    },
    closeGroupDialog() {
      this.addGroup = {
        name: null
      }
      this.groupIsDisabled = false
    },
    saveGroup() {
      if (this.addGroup.id === null || this.addGroup.id === undefined) {
        // save
        addGroup(this.addGroup.name).then(() => {
          this.$message.success("成功添加分组！")
          this.getSaveConnectList()
          this.groupDialog = false
        }).catch(() => {
          this.$message.error("添加分组失败！")
        })
      } else {
        // edit
        editGroup(this.addGroup.id, this.addGroup.name).then(() => {
          this.$message.success("成功修改分组！")
          this.getSaveConnectList()
          this.groupDialog = false
        }).catch(() => {
          this.$message.error("修改分组失败！")
        })
      }
    },
    beforeOpenConnectDialog(connect) {
      this.connectDialog = true
      this.dialogTitle = "编辑连接"
      this.connectForm.id = connect.id
      this.connectForm.auth = connect.auth
      this.connectForm.name = connect.name
      this.connectForm.groups = connect.groupId
      this.connectForm.protocol = connect.protocol
      this.connectForm.ip = connect.ip
      this.connectForm.port = connect.port
      this.connectForm.username = connect.username
      this.connectForm.password = connect.password
      this.connectForm.authDatabase = connect.authDatabase
      this.connectForm.authMechanism = connect.authMechanism
    },
    openConnectDialog() {
      this.$refs.nameInput.focus();
    },
    closeConnectDialog() {
      this.connectForm = {
        id: null,
        name: null,
        groups: null,
        protocol: null,
        ip: null,
        port: null,
        auth: null,
        username: null,
        password: null,
        authDatabase: null,
        authMechanism: null,
      }
    },
    saveConnect() {
      let groups = []
      groups.push(this.connectForm.groups)
      this.connectForm.groups = groups
      editConnection(this.connectForm).then(() => {
        this.$message.success("成功修改连接！")
        this.getSaveConnectList()
        this.connectDialog = false
      }).catch(() => {
        this.$message.error("修改连接失败！")
      })
    },
    ImportConnection() {
      const loading = this.$loading({
        lock: true,
        text: '导入中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        importSaveConnectList(this.importDate.saveConnections).then(() => {
          this.$message.success("成功导入连接！")
          this.getSaveConnectList()
          this.importConnectionDialog = false
        }).catch(() => {
          this.$message.error("导入连接失败！")
        })
      }, 1000);
    },
    openImportConnectionDialog() {
    },
    closeImportConnectionDialog() {
    },
    importExceed() {
      this.$alert('只能上传一个文件！', '上传错误', {
        confirmButtonText: '确认'
      });
    },
    importFileChange(file, fileList) {
      const fileSuffix = file.name.substring(file.name.lastIndexOf(".") + 1);

      const whiteList = ["json"];

      if (whiteList.indexOf(fileSuffix) === -1) {
        this.$alert('上传文件只能是 json 格式', '上传错误', {
          confirmButtonText: '确认',
          type: 'error'
        });
        fileList.pop()
        return false;
      }

      const isLt10M = file.size / 1024 / 1024 < 10;

      if (!isLt10M) {
        this.$alert('上传文件大小不能超过 10MB', '上传错误', {
          confirmButtonText: '确认',
          type: 'error'
        });
        fileList.pop()
        return false;
      }
      const reader = new FileReader();
      reader.readAsText(file.raw)
      reader.onload = (e) => {
        this.importDate = JSON.parse(e.target.result)
      }
    },
    ExportConnection() {
      this.exportList.forEach(item => {
        delete item.groupId
        delete item.id
        delete item.type
        delete item.updateTime
        delete item.userId
      })
      let exportDate = {
        saveConnections: this.exportList
      }
      const data = JSON.stringify(exportDate, null, 2);
      const blob = new Blob([data], {type: 'application/json'});
      const loading = this.$loading({
        lock: true,
        text: '导出中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        FileSaver.saveAs(blob, 'save-connections.json')
        this.exportConnectionDialog = false
      }, 1000);
    },
    openExportConnectionDialog() {

    },
    closeExportConnectionDialog() {

    },
    handleSelectionChange(value) {
      this.connectionMultipleSelection = value
      let selectionList = []
      this.$refs.multipleTable.forEach(table => {
        table.selection.forEach(item => {
          this.saveConnectionGroups.forEach(group => {
            if (item.groupId === group.id) {
              item.groupName = group.groupName
            }
          })
          selectionList.push(item)
        })
      })
      this.exportList = selectionList
    },
    openConnection(row) {
      const loading = this.$loading({
        lock: true,
        text: '连接中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        row.groups = [row.groupId]
        let data = JSON.parse(JSON.stringify(row))
        this.$store.dispatch("Connect", data).then(() => {
          this.$router.push({path: "/connection"})
        }).catch(() => {
          this.$message.error("连接失败！")
        })
      }, 1000);
    },
    copyConnectionString(row) {
      navigator.clipboard.writeText(row.uri).then(() => {
        this.$message.success('Copy成功！')
      })
    },
    duplicate(row) {
      addConnection(row, {name: row.name + '(copy)', groups: row.groupId}).then(() => {
        this.$message.success('成功复制连接！')
        this.getSaveConnectList()
      }).catch(() => {
        this.$message.error('复制连接失败！')
      })
    }
  }
}
</script>

<style scoped>
.contain {
  padding: 20px;
}
</style>
